from google.appengine.ext import db
from app.helpers.simplify import simplify


class KeyString(unicode):
  """ String with a key attribute
  
  We use key for comparison since the actual user-entered value may have
  small irregularities (caps, punctuation, etc)
  
  """
  _simplify_function = simplify
  
  def __init__(self, *args, **kwargs):
    self.key = unicode(self.__class__._simplify_function(self))
    super(KeyString, self).__init__(*args, **kwargs)
  
  def __eq__(self, x):
    x = KeyString(x)
    return self.key == x.key
  
  def __ne__(self, x):
    x = KeyString(x)
    return self.key != x.key
  
  def __lt__(self, x):
    x = KeyString(x)
    return self.key < x.key
  
  def __le__(self, x):
    x = KeyString(x)
    return self.key <= x.key
  
  def __gt__(self, x):
    x = KeyString(x)
    return self.key > x.key
  
  def __ge__(self, x):
    x = KeyString(x)
    return self.key >= x.key
  
  def __add__(self, x):
    return KeyString(unicode(self) + unicode(x))


class KeyStringProperty(db.Property):
  """ Property for loosely-valued user-entered strings
  
  When dealing with user entered data, we really want to store two
  string values -- the actual data entered and the 'simplifed' version
  on which it's easier to do exact match lookups. We do this by using
  a string list to store both copies in a single value -- AppEngine's
  query syntax for lists makes this work out rather nicely
  
  """
  data_type = KeyString
  
  verbose_type = 'Keyword'
  
  def get_value_for_datastore(self, model_instance):
    keystring = super(KeyStringProperty,
                 self).get_value_for_datastore(model_instance)
    if keystring:
      return [unicode(keystring), keystring.key]
    else:
      return None
      
  def get_value_for_lookup(self, model_instance):
    value = self.get_value_for_datastore(model_instance)
    if value:
      string, key = value
      return key
  
  def get_value_for_sort(self, model_instance):
    return self.get_value_for_lookup(model_instance)
  
  def get_value_for_tag(self, model_instance):
    keystring = super(KeyStringProperty,
                 self).get_value_for_datastore(model_instance)
    if keystring:
      return unicode(keystring)
    else:
      return None
    
  def make_value_for_query(self, value):
    if value is None: return value
    return KeyString(value).key
  
  def make_value_from_datastore(self, value):
    try:
      return KeyString(value[0])
    except (IndexError, TypeError):
      return None
  
  def validate(self, value):
    if not value:
      value = None
    elif not isinstance(value, KeyString):
      value = KeyString(value)
    return super(KeyStringProperty, self).validate(value)
  
  def empty(self, value):
    return not value
